import compute from '../lib/Compute';
import {
  trimSpace,
  digitalize
} from '../utils/tools';
import ResultComponent from '../components/Result/index';
import InputGroupComponent from '../components/InputGroup/index';
import BtnGroupComponent from '../components/BtnGroup/index';



@compute
export default class Calculator {
  constructor(el) {
    this.name = 'Calculator';
    this.el = el;
    this.resultComponent = new ResultComponent();
    this.inputGroupComponent = new InputGroupComponent();
    this.btnGroupComponent = new BtnGroupComponent();
    this.data = this.defineData();
    console.log(this.data);
    this.selectedIndex = 0;
  }

  init() {
    this.render()
    this.bindEvent()
  }

  defineData() {
    // let _obj = {},
    //   method = 'plus',
    //   fVal = 0,
    //   sVal = 0;

    // const _self = this;
    // Object.defineProperties(_obj, {
    //   //属性名
    //   method: {
    //     get() {
    //       return method;
    //     },
    //     set(newVal) {
    //       method = newVal;
    //       _self.setResult(_self.data.method, _self.data.fVal, _self.data.sVal)
    //     }
    //   },
    //   fVal: {
    //     get() {
    //       return fVal;
    //     },
    //     set(newVal) {
    //       fVal = newVal;
    //       _self.setResult(_self.data.method, _self.data.fVal, _self.data.sVal)
    //     }
    //   },
    //   sVal: {
    //     get() {
    //       return sVal;
    //     },
    //     set(newVal) {
    //       sVal = newVal;
    //       _self.setResult(_self.data.method, _self.data.fVal, _self.data.sVal)
    //     }
    //   }
    // });
    // return _obj;

    let target = {
      method: 'plus',
      fVal: 0,
      sVal: 0
    };
    const _self = this;
    //第一个参数为一个对象
    //第二个参数也是一个对象
    return new Proxy(target, {
      //第一个参数为对象本身，第二参数为属性
      get(target, prop) {
        //直接返回属性值
        return target[prop]
      },
      set(target, prop, value) {
        //当前对象属性值要赋值为value
        target[prop] = value;
        _self.setResult(_self.data.method, _self.data.fVal, _self.data.sVal)
        return true;
      }
    });
  }

  render() {
    const oFrag = document.createDocumentFragment();
    oFrag.appendChild(this.resultComponent.tpl());
    oFrag.appendChild(this.inputGroupComponent.tpl());
    oFrag.appendChild(this.btnGroupComponent.tpl());
    this.el.appendChild(oFrag);
  }
  bindEvent() {
    const el = this.el;
    this.oResult = el.getElementsByClassName('result')[0];
    this.oBtnGroup = el.getElementsByClassName('button-group')[0];
    this.oInputs = el.getElementsByClassName('num-input');
    this.oBtns = this.oBtnGroup.getElementsByClassName('btn');
    this.oBtnGroup.addEventListener('click', this.onBtnClick.bind(this), false);
    this.oInputs[0].addEventListener('input', this.onInput.bind(this), false);
    this.oInputs[1].addEventListener('input', this.onInput.bind(this), false);
  }

  onBtnClick(ev) {
    const e = ev || window.event,
      tar = e.target || e.srcElement,
      tagName = tar.tagName.toLowerCase();
    if (tagName === 'button') {
      const method = tar.getAttribute('data-method');
      this.setData('method', method);
      this.setBtnSelected(tar);
    }
  }

  onInput(ev) {
    const e = ev || window.event,
      tar = e.target || e.srcElement,
      id = tar.getAttribute('data-id'),
      val = digitalize(trimSpace(tar.value)) ||
      0;
    this.setData(id, val);
  }

  setData(field, newVal) {
    switch (field) {
      case 'method':
        this.data.method = newVal;
        break;
      case 'fVal':
        this.data.fVal = newVal;
        break;
      case 'sVal':
        this.data.sVal = newVal;
        break;
      default:
        break;
    }
  }

  setBtnSelected(target) {
    this.oBtns[this.selectedIndex].className = 'btn';
    this.selectedIndex = [].indexOf.call(this.oBtns, target);
    this.oBtns[this.selectedIndex].className = 'btn selected';
  }
  setResult(method, fVal, sVal) {
    this.oResult.innerText = this[method](fVal, sVal);
  }
}